/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#include <stdarg.h>
#include "设备内存缓存.h"

#include "底层绘图/intern/Vulkan/buffer/Vk缓存.h"

struct S_缓存调试分配记录 {
	std::string fileName;
	uint32 编号;
};

static std::map<S_板载缓存*, uint32> 分配释放记录;
//static std::set<S_板载缓存*> 分配释放记录;
static std::mutex g缓存分配锁;




/*#ifdef _DEBUG  

S_板载缓存* f_buf_create板载缓存(S_设备环境 ctx, uint16 offset, E_板载缓存类型 type, uint64 size, const std::string fileName, uint32 行号) {
	S_板载缓存* buf = 0;
	switch (ctx.m_Type) {
	case E_Vulkan:
		buf = new S_VkArray缓存(ctx, offset, type, size);
		break;

	case E_DirectX12:
		break;
	default:
		break;
	}
	assert(offset);
	S_缓存调试分配记录 记录 = {fileName, 行号};
	分配释放记录[buf] = 记录;

	return buf;
}


S_板载缓存* f_buf_create板载缓存(S_设备环境 ctx, E_板载缓存类型 type, uint32 typeflags, uint16 offset, uint64 size, const std::string fileName, uint32 行号) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, type, f_getVk缓存类型(typeflags), offset, size);
	S_缓存调试分配记录 记录 = {fileName, 行号};
	分配释放记录[buf] = 记录;
	return buf;
}


S_板载缓存* f_buf_create板载缓存(S_设备环境 ctx, E_板载缓存类型 type, uint16 offset, const std::string fileName, uint32 行号) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, offset, type, 0);

	S_缓存调试分配记录 记录 = {fileName, 行号};
	分配释放记录[buf] = 记录;

	assert(offset);
	return buf;
}


#else


#endif*/






S_板载缓存* f_buf_create板载缓存(S_设备环境 ctx, uint16 offset, E_板载缓存类型 type, uint64 size) {
	S_板载缓存* buf = 0;
	switch (ctx.m_Type) {
	case E_Vulkan:
		buf = new S_VkArray缓存(ctx, offset, type, size);
		break;

	case E_DirectX12:
		break;
	default:
		break;
	}
	assert(offset);
	g缓存分配锁.lock();
	if (分配释放记录.size() == 241) {
		std::cout << "a" << std::endl;
	}
	分配释放记录[buf] = 分配释放记录.size();
	g缓存分配锁.unlock();
	return buf;
}


S_板载缓存* f_buf_create板载缓存(S_设备环境 ctx, E_板载缓存类型 type, uint32 typeflags, uint16 offset, uint64 size) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, type, f_getVk缓存类型(typeflags), offset, size);
	//分配释放记录.insert(buf);
	g缓存分配锁.lock();
	if (分配释放记录.size() == 241) {
		std::cout << "a" << std::endl;
	}
	分配释放记录[buf] = 分配释放记录.size();
	g缓存分配锁.unlock();
	return buf;
}


S_板载缓存* f_buf_create板载缓存(S_设备环境 ctx, E_板载缓存类型 type, uint16 offset) {
	S_板载缓存* buf = new S_VkArray缓存(ctx, offset, type, 0);
	assert(offset);
	//分配释放记录.insert(buf);
	g缓存分配锁.lock();
	if (分配释放记录.size() == 241) {
		std::cout<<"a"<<std::endl;
	}
	分配释放记录[buf] = 分配释放记录.size();
	g缓存分配锁.unlock();
	return buf;
}




void f_buf_release板载缓存(S_板载缓存* buf) {
	g缓存分配锁.lock();
	分配释放记录.erase(buf);
	g缓存分配锁.unlock();

#ifdef _DEBUG  
	
#else

#endif

	delete buf;
}

void f_buf_释放所有() {
	uint32 id = 0;
	for (auto& e : 分配释放记录) {
		std::cout<<e.second<<" :"<<id<<std::endl;
		delete e.first;
		++id;
	}
}




uint32 f_get缓存布局类型(E_板载缓存类型 memType) {
	uint32 mt = 0;
	//VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
	switch (memType)
	{
	case e_UBO:		mt = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; break;
	case e_TBOs:	mt = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break;
	case e_VBO:	
	case e_INDEX:	//mt = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; break;
	case e_SSBO:	mt = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; break;
	case e_SSBOd:	mt = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; break;
		//case e_INDEX:	mt = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; break;
	case e_光追底层加速结构:
	case e_光追顶层加速结构:
	case e_光追BVH:	mt = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; break;

	case E_板载缓存类型::e_IMAGE: mt = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; break;
	case E_板载缓存类型::e_SAMPLER: mt = VK_DESCRIPTOR_TYPE_SAMPLER; break;
	case E_板载缓存类型::e_IMAGE_SAMPLER: mt = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; break;
	default:
		break;
	}
	return mt;
}




void f_fill板载缓存(S_板载缓存* obj, const vector<vec3>& data, E_板载缓存类型 memType, S_设备环境& ctx) {
	obj->m_Size = data.size();
	obj->m_Offset = sizeof(vec3);
	obj->f_fillData(data.data(), data.size() * sizeof(vec3));
}


void f_fill板载缓存(S_板载缓存* obj, const vector<uint32>& data, E_板载缓存类型 memType, S_设备环境& ctx) {
	obj->m_Size = data.size();
	obj->m_Offset = sizeof(uint32);
	obj->f_fillData(data.data(), data.size() * sizeof(uint32));
}



void f_fill板载缓存(S_板载缓存* obj, const vector<Mat44f>& data, E_板载缓存类型 memType, S_设备环境& ctx) {
	obj->m_Size = data.size();
	obj->m_Offset = sizeof(Mat44f);
	obj->f_fillData(data.data(), data.size() * sizeof(Mat44f));
}

void f_fill板载缓存(S_板载缓存* obj, const Mat44f* data, uint64 offset) {
	obj->f_map();
	((Mat44f*)obj->m_mappedPtr)[offset] = *data;
	obj->f_unmap();
}

void f_buf_set(S_板载缓存* obj, int8 val) {
	obj->f_map();
	memset(obj->m_mappedPtr, val, obj->m_Offset * obj->m_Size);
	obj->f_unmap();
}

void f_buf_fill(S_板载缓存* obj, const void* val, uint64 num) {
	obj->f_fillData(val, obj->m_Offset * num);
}



void f_buf_resize(S_板载缓存* obj, uint32 size) {
	assert(size != 0);
	if(obj->m_Size == size) 
		return;
	uint64 bitsize = obj->m_Offset * size;
	
	obj->m_Size = size;
	obj->f_resize(bitsize);
}

void f_buf_erase(S_板载缓存* obj, uint32 loc, uint32 num) {
	obj->f_map();
	uint64 offset = num * obj->m_Offset;
	//uint64 offset_end = loc * obj->m_Offset + num * obj->m_Offset;
	uint64 len = obj->m_Size * obj->m_Offset - offset;
	for (uint64 i = loc * obj->m_Offset; i < len; ++i) {
		((uint8*)obj->m_mappedPtr)[i] = ((uint8*)obj->m_mappedPtr)[offset + i];
	}
	//S_Array array = { (uint8*)obj->m_mappedPtr, obj->m_Size };
	//f_core_array_erase(&array, loc, 1);
	//obj->m_Size = array.count;
	obj->m_Size -= num;
	obj->f_unmap();
}

bool f_resize板载缓存_Up(S_板载缓存* obj, uint64 size) {
	if (size > obj->m_Size) {
		uint64 bitsize = obj->m_Offset * size;
		obj->f_resize(bitsize);
	}
	obj->m_Size = size;
	return true;
}

void f_change板载缓存(S_板载缓存* obj, E_板载缓存类型 memType) {
	auto* temp = obj;
	//f_create板载缓存(obj->m)
}

void f_popend板载缓存(S_板载缓存* obj, int64 id) {
	if (id < 0) {
		f_buf_resize(obj, obj->m_Size--);
	}
	else {
		obj->f_map();
		//((uint8*)obj->m_mappedPtr)[0] = data;
		obj->f_unmap();
	}
}







void f_clear板载缓存(S_板载缓存* obj) {
	obj->f_resize(obj->m_Offset);
	obj->m_Size = 0;
}

void f_buf_insert(S_板载缓存* obj, int64 offset, const void* data, uint32 size) {
	assert(size);
	//if (offset >= obj->m_Size) {
		obj->m_Size += size;
		obj->f_resize(obj->m_Size * obj->m_Offset);
	//}
	//else {
		//obj->m_Size += size;
	//}
	
	uint64 startoffset = offset * obj->m_Offset;
	uint64 appendOffset = (offset + size) * obj->m_Offset;
	uint64 newDataSize = size * obj->m_Offset;
	uint64 后面一节数据的数量 = obj->m_Size - offset;

	void* temp = calloc(后面一节数据的数量, obj->m_Offset);
	后面一节数据的数量 *= obj->m_Offset;

	obj->f_map();
	memcpy(temp, &(((int8*)obj->m_mappedPtr)[startoffset]), 后面一节数据的数量);
	memcpy(&(((int8*)obj->m_mappedPtr)[appendOffset]), temp, 后面一节数据的数量);
	memcpy(&(((int8*)obj->m_mappedPtr)[startoffset]), data, newDataSize);
	obj->f_unmap();

	free(temp);
}












/*void f_buf_resize(uint64 count, uint16 num, ...) {
	va_list 参数表;

	va_start(参数表, num);

	for (uint16 i = 0; i < num; ++i) {
		S_板载缓存* b = va_arg(参数表, S_板载缓存*);

		f_buf_resize(b, count);
	}

	va_end(参数表);
}*/





















